﻿
// DataSynAppDlg.cpp: 实现文件
//

#include "pch.h"
#include "framework.h"
#include "DataSynApp.h"
#include "DataSynAppDlg.h"
#include "afxdialogex.h"
#include <iostream>
#include <json/json.h> // 引入 jsoncpp 头文件
#include <curl/curl.h>     // libcurl 头文件
#include <chrono>
#include <fstream>
#include <afxmt.h>
#include <regex>
#include <comdef.h>
#include <atlbase.h>
#include <atldbcli.h>
#include "Set.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#include <iomanip>

CMutex m_mutex; // 互斥对象
std::map<CString, std::map<CString, CString>> iniData;
CDataSynApp* appDlg;
// 回调函数，用于处理 libcurl 响应数据
size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp)
{
	((std::string*)userp)->append((char*)contents, size * nmemb);
	return size * nmemb;
}

// 向指定 URL 发送 JSON 数据的 POST 请求
std::string PostJsonToUrl(const std::string& url, const std::string& jsonData)
{
	CURL* curl;
	CURLcode res;
	std::string readBuffer;

	curl = curl_easy_init();

	if (curl) {
		struct curl_slist* headers = NULL;

		// 设置请求头
		headers = curl_slist_append(headers, "Content-Type: application/json");
		headers = curl_slist_append(headers, "Accept: application/json");

		curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
		curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonData.c_str());
		curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, jsonData.size());
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
		curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);

		// 执行请求
		res = curl_easy_perform(curl);

		// 检查是否出现错误
		if (res != CURLE_OK) {
			AfxMessageBox(CString(curl_easy_strerror(res)));
		}

		// 清理
		curl_slist_free_all(headers);
		curl_easy_cleanup(curl);
	}

	return readBuffer;
}

long PerformGetRequest(const std::string url) {
	CURL* curl;
	CURLcode res;
	std::string readBuffer;
	long response_code = 0;  // 用于存储返回的HTTP状态码

	curl = curl_easy_init();
	if (curl) {
		// 设置URL
		curl_easy_setopt(curl, CURLOPT_URL, url.c_str());

		// 设置写数据的回调函数
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
		// 设置回调函数的参数，这里是我们要接收数据的字符串
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);

		// 执行请求
		res = curl_easy_perform(curl);

		// 检查请求是否成功
		if (res == CURLE_OK) {
			// 获取HTTP状态码
			curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
		}
		else {
			// 请求失败时输出错误信息
			// AfxMessageBox(("Error: " + std::string(curl_easy_strerror(res))).c_str());
		}

		// 清理
		curl_easy_cleanup(curl);
	}

	// 返回HTTP状态码
	return response_code;
}

class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_ABOUTBOX };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CDataSynApp 对话框



CDataSynApp::CDataSynApp(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_DataSynApp_DIALOG, pParent)
	
	, DRILLID(_T(""))
	, b_work(false)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CDataSynApp::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_LIST1, m_listBox);
	DDX_Control(pDX, IDC_STATIC_pic, m_pictureCtrl);
	DDX_Control(pDX, IDC_STATIC_chi_non, chi_non);
	DDX_Control(pDX, IDC_STATIC_chi_send, chi_send);
	DDX_Control(pDX, IDC_STATIC_name, jing_name);
	DDX_Text(pDX, IDC_EDIT2, DRILLID);
	DDX_Control(pDX, IDC_LIST2, m_listBox_zg);
	DDX_Control(pDX, IDC_STATIC_zg_n, zg_non);
	DDX_Control(pDX, IDC_STATIC_zgsend, zg_send);
}

BEGIN_MESSAGE_MAP(CDataSynApp, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON1, &CDataSynApp::OnBnClickedButton1)
	ON_BN_CLICKED(IDC_BUTTON3, &CDataSynApp::OnBnClickedButton3)
	ON_BN_CLICKED(IDC_BUTTON4, &CDataSynApp::OnBnClickedButton4)
	ON_BN_CLICKED(IDC_BUTTON2, &CDataSynApp::OnBnClickedButton2)
	ON_WM_CLOSE()
	ON_STN_CLICKED(IDC_STATIC_pic, &CDataSynApp::OnStnClickedStaticpic)
	ON_BN_CLICKED(IDC_BUTTON5, &CDataSynApp::OnBnClickedButton5)
END_MESSAGE_MAP()


CString GetExePath() {
	TCHAR path[MAX_PATH];
	// GetModuleFileName retrieves the full path of the current executable
	if (GetModuleFileName(NULL, path, MAX_PATH)) {
		CString exePath(path);
		// Extract directory by removing the executable name from the full path
		int lastSlashIndex = exePath.ReverseFind('\\');
		if (lastSlashIndex != -1) {
			exePath = exePath.Left(lastSlashIndex + 1);
		}
		return exePath;
	}
	return _T("");
}
void CDataSynApp::readini() {
	m_mutex.Lock(); // 获取互斥锁
	iniData = ReadIniFile(exePath);

	// Print out the content of the INI file (for debug purposes)
	for (const auto& section : iniData) {
		std::cout << _T("[") << section.first.GetString() << _T("]") << std::endl;
		for (const auto& keyValue : section.second) {
			std::cout << keyValue.first.GetString() << _T("=") << keyValue.second.GetString() << std::endl;
		}
		std::cout << std::endl;
	}


	DBType = iniData[_T("SysTem")][_T("DBType")];
	DBServer = iniData[_T("SysTem")][_T("DBServer")];
	DBPORT = iniData[_T("SysTem")][_T("DBPORT")];
	DBSVName = iniData[_T("SysTem")][_T("DBSVName")];
	DBUser = iniData[_T("SysTem")][_T("DBUser")];
	DBPwd = iniData[_T("SysTem")][_T("DBPwd")];
	DBName = iniData[_T("SysTem")][_T("DBName")];

	DBPath = iniData[_T("AccessDB")][_T("DBPath")];

	WELLID = iniData[_T("Data")][_T("WELLID")];
	DRILLID = iniData[_T("Data")][_T("DRILLID")];

	SendType = iniData[_T("SendData")][_T("SendType")];
	ZGtime = iniData[_T("SendDateTime")][_T("ZGtime")];
	BJtime = iniData[_T("SendDateTime")][_T("BJtime")];

	CTime currentTime = CTime::GetCurrentTime(); // 获取当前时间
	CString strDate;
	strDate.Format(_T("%04d-%02d-%02d 00:00:00"), currentTime.GetYear(), currentTime.GetMonth(), currentTime.GetDay()); // 格式化日期为YYYY-MM-DD

	if (SendType = "") {
		iniData[_T("SendData")][_T("SendType")] = "1";
		WriteIniFile(exePath, iniData);
	}
	if (ZGtime==""){
		iniData[_T("SendDateTime")][_T("ZGtime")] = strDate;
		WriteIniFile(exePath, iniData);

	}
	if (BJtime==""){
		iniData[_T("SendDateTime")][_T("BJtime")] = strDate;
		WriteIniFile(exePath, iniData);
	}

	if (SendType == "0") {
		strSendRemote = "http://10.76.204.106:8080";
	}
	else {
		strSendRemote = "http://114.251.197.140:8080";
	}
	strWellName = DBPath;
	int lastSlashPos = strWellName.ReverseFind('\\');
	if (lastSlashPos != -1)
		strWellName = strWellName.Mid(lastSlashPos + 1);

	// 去除文件扩展名
	int dotPos = strWellName.ReverseFind(_T('.'));
	if (dotPos != -1)
		strWellName = strWellName.Left(dotPos);
	jing_name.SetWindowTextA(strWellName);


	CButton* pButton = (CButton*)GetDlgItem(IDC_BUTTON3);
	if (pButton != nullptr) {
		pButton->SetWindowText(strWellName);
	}


	m_mutex.Unlock(); // 释放互斥锁
}
UINT  ping(LPVOID pParam)
{
	CDataSynApp* dlg = static_cast<CDataSynApp*>(pParam);
	while (true) {
		dlg->readini();
		long response_code = PerformGetRequest(dlg->strSendRemote.GetString());
		if (response_code == 200) {
			dlg->setnet("./res/NETO.bmp");
		}
		else {
			dlg->setnet("./res/NETC.bmp");
		}
		Sleep(30 * 1000);
	}
	return FALSE;
}
BOOL CDataSynApp::OnInitDialog()
{
	CDialogEx::OnInitDialog();
	appDlg = this;
	// 将“关于...”菜单项添加到系统菜单中。
	ModifyStyle(WS_THICKFRAME, 0);
	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);
	curl_global_init(CURL_GLOBAL_DEFAULT);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != nullptr)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时，框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	LONG lStyle;
	lStyle = GetWindowLong(m_listBox.m_hWnd, GWL_STYLE);//获取当前窗口style
	lStyle &= ~LVS_TYPEMASK; //清除显示方式位
	lStyle |= LVS_REPORT; //设置style
	lStyle |= LVS_SINGLESEL;//单选模式
	SetWindowLong(m_listBox.m_hWnd, GWL_STYLE, lStyle);//设置style
	SetWindowLong(m_listBox_zg.m_hWnd, GWL_STYLE, lStyle);//设置style

	DWORD dwStyle = m_listBox.GetExtendedStyle();
	dwStyle |= LVS_EX_FULLROWSELECT;//选中某行使整行高亮（只适用与report风格的listctrl）
	dwStyle |= LVS_EX_GRIDLINES;//网格线（只适用与report风格的listctrl）
	//dwStyle |= LVS_EX_CHECKBOXES;//item前生成checkbox控件
	m_listBox.SetExtendedStyle(dwStyle); //设置扩展风格
	m_listBox_zg.SetExtendedStyle(dwStyle); //设置扩展风格

	m_listBox.InsertColumn(0, _T("池"), LVCFMT_CENTER, 50, 0);
	m_listBox.InsertColumn(1, _T("数据时间"), LVCFMT_CENTER, 207, 1);

	m_listBox_zg.InsertColumn(0, _T("坐岗"), LVCFMT_CENTER, 50, 0);
	m_listBox_zg.InsertColumn(1, _T("数据时间"), LVCFMT_CENTER, 207, 1);

	exePath = GetExePath();
	std::cout << _T("Current EXE Path: ") << exePath.GetString() << std::endl;
	exePath += "DataSynApp.ini";

	readini();

	setnet("./res/NETC.bmp");

	CWinThread* pThread = ::AfxBeginThread(ping, this);
	if (pThread != NULL)
	{
		TRACE(_T("Thread started, ID: %u\n"), pThread->m_nThreadID);
	}
	else
	{
		::AfxMessageBox(_T("Failed to create thread."));
	}

	UpdateData(false);

	return TRUE;  // 除非将焦点设置到控件，否则返回 TRUE
}

void CDataSynApp::setnet(char* net)
{
	// 加载BMP图片
	HBITMAP hBitmap = (HBITMAP)LoadImage(AfxGetInstanceHandle(),
		net, // 图片路径，相对或绝对
		IMAGE_BITMAP,
		0, 0, // 使用实际大小
		LR_CREATEDIBSECTION | LR_LOADFROMFILE);
	if (hBitmap != NULL)
	{
		// 设置图片到Picture Control
		m_pictureCtrl.SetBitmap(hBitmap);
	}
	else
	{
		// 处理加载失败的情况
		AfxMessageBox(_T("Failed to load bitmap."));
	}

}
void CDataSynApp::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮，则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序，
//  这将由框架自动完成。

void CDataSynApp::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CDataSynApp::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}
std::string VariantToString(const _variant_t& vtValue)
{
	// 检查 _variant_t 是否包含 BSTR (宽字符字符串)
	if (vtValue.vt == VT_BSTR)
	{
		// 使用 _bstr_t 将 BSTR 转换为 char*，然后转换为 std::string
		_bstr_t bstrVal(vtValue);
		return std::string((const char*)bstrVal);
	}
	else
	{
		// 如果不是字符串类型，根据需要处理其他类型
		return "";
	}
}

std::string strTVOLInfo[24];

void GetSet(_ConnectionPtr pConnection) {
	try {
		_RecordsetPtr pRecordset;
		pRecordset.CreateInstance(__uuidof(Recordset));

		std::string sqlQuery = "SELECT TankSet FROM TankSet";
		pRecordset->Open(sqlQuery.c_str(),
			_variant_t((IDispatch*)pConnection, true),
			adOpenStatic,
			adLockOptimistic,
			adCmdText);

		if (!pRecordset->adoEof) {
			_variant_t varTankSet = pRecordset->Fields->GetItem("TankSet")->Value;
			if (varTankSet.vt != VT_NULL) {
				std::string tankSetStr = (const char*)_bstr_t(varTankSet.bstrVal);

				std::vector<std::string> tankGroups;
				std::regex atSplitter("@");
				std::copy(std::sregex_token_iterator(tankSetStr.begin(), tankSetStr.end(), atSplitter, -1),
					std::sregex_token_iterator(),
					std::back_inserter(tankGroups));

				for (int i = 0; i < tankGroups.size(); ++i) {
					std::vector<std::string> tankInfo;
					std::regex colonSplitter(":");
					std::copy(std::sregex_token_iterator(tankGroups[i].begin(), tankGroups[i].end(), colonSplitter, -1),
						std::sregex_token_iterator(),
						std::back_inserter(tankInfo));

					if (tankInfo.size() == 2) {
						std::string tankName = tankInfo[0];

						std::vector<std::string> sensorIds;
						std::regex commaSplitter(",");
						std::copy(std::sregex_token_iterator(tankInfo[1].begin(), tankInfo[1].end(), commaSplitter, -1),
							std::sregex_token_iterator(),
							std::back_inserter(sensorIds));

						for (const std::string& sensorIdStr : sensorIds) {
							int sensorId = std::stoi(sensorIdStr);
							if (sensorId >= 1 && sensorId <= 24) {
								strTVOLInfo[sensorId - 1] = tankName;
							}
						}
					}
				}
			}
		}

		pRecordset->Close();
	}
	catch (_com_error& e) {
		std::cerr << "Error: " << e.ErrorMessage() << std::endl;
	}
}


std::string toString(const Json::Value& val) {
	static Json::Value def = []() {
		Json::Value def;
		Json::StreamWriterBuilder::setDefaults(&def);
		def["emitUTF8"] = true;
		return def;
		}();

	Json::StreamWriterBuilder writer;
	writer.settings_ = def; // Config emitUTF8
	writer.settings_["precision"] = 4; // 设置精度为4位小数
	writer.settings_["indentation"] = ""; // 不使用缩进

	std::ostringstream stream;
	std::unique_ptr<Json::StreamWriter> jsonWriter(writer.newStreamWriter());
	jsonWriter->write(val, &stream);
	return stream.str();
}
// 获取13位时间戳的函数
static __int64 GetUnixTime()
{
	std::string nowTimeUnix;
	std::string cs_uninxtime;
	std::string cs_milliseconds;
	SYSTEMTIME sysTime;
	GetLocalTime(&sysTime);
	time_t unixTime;
	time(&unixTime);
	char buf[30], buf1[30];
	sprintf_s(buf, sizeof(buf), "%I64d", (INT64)unixTime);
	sprintf_s(buf1, sizeof(buf1), "%03I64d", (INT64)sysTime.wMilliseconds);
	nowTimeUnix = std::string(buf) + std::string(buf1);
	return _atoi64(nowTimeUnix.c_str());
}
std::string ConvertRecordsetToJson(_RecordsetPtr& pRecordset, std::string wellname)
{
	// 确保 pRecordset 不为空
	if (!pRecordset)
	{
		return "{}";
	}

	std::string strTime = (const char*)_bstr_t(pRecordset->Fields->GetItem("TIME")->Value);
	size_t pos = 0;
	while ((pos = strTime.find("-", pos)) != std::string::npos) {
		strTime.replace(pos, 1, "/");
		pos += 1; // 移动到替换后的位置避免死循环
	}
	double dTvol01 = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("TVOL01")->Value));
	double dTvol02 = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("TVOL02")->Value));
	double dTvol03 = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("TVOL03")->Value));
	double dTvol04 = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("TVOL04")->Value));
	double dTvol05 = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("TVOL05")->Value));
	double dTvol06 = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("TVOL06")->Value));
	double dTvol07 = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("TVOL07")->Value));
	double dTvol08 = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("TVOL08")->Value));
	double dTvol09 = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("TVOL09")->Value));
	double dTvol10 = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("TVOL10")->Value));
	double dTvol11 = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("TVOL11")->Value));
	double dTvol12 = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("TVOL12")->Value));
	double dTvol13 = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("TVOL13")->Value));
	double dTvol14 = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("TVOL14")->Value));
	double dTvol15 = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("TVOL15")->Value));
	double dTvol16 = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("TVOL16")->Value));
	double dTvol17 = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("TVOL17")->Value));
	double dTvol18 = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("TVOL18")->Value));
	double dTvol19 = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("TVOL19")->Value));
	double dTvol20 = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("TVOL20")->Value));
	double dTvol21 = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("TVOL21")->Value));
	double dTvol22 = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("TVOL22")->Value));
	double dTvol23 = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("TVOL23")->Value));
	double dTvol24 = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("TVOL24")->Value));

	double dSpm1 = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("SPM1")->Value));
	double dSpm2 = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("SPM2")->Value));
	double dSpm3 = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("SPM3")->Value));
	double dConin = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("CONIN")->Value));
	double dConout = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("CONOUT")->Value));
	double dFlowout = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("FLOWOUT")->Value));
	double dClout = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("CLOUT")->Value));
	double dTvol = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("TVOL")->Value));
	double dMudgl = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("MUDGL")->Value));
	double dTtvol = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("TTVOL")->Value));
	double dTtvolgl = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("TTVOLGL")->Value));
	double dMudglrate = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("MUDGLRATE")->Value));
	double dTtvolglrate = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("TTVOLGLRATE")->Value));
	double dTotalpump = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("TOTALPUMP")->Value));
	double dFlowin = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("FLOWIN")->Value));
	double dFlowdiff = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("FLOWDIFF")->Value));
	double dCondiff = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("CONDIFF")->Value));
	double dTvolbl = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("TVOLBL")->Value));
	double dGs = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("GS")->Value));
	double dLs = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("LS")->Value));
	double dCs = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("CS")->Value));
	double dWsv = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("WSVOL")->Value));
	double dDepth = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("DEPTH")->Value));
	double dBitdepth = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("BITDEPTH")->Value));
	double dSpp = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("SPP")->Value));
	double dCasep = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("CASEP")->Value));
	double dTg = std::stod((const char*)_bstr_t(pRecordset->Fields->GetItem("TG")->Value));

	std::string strREALINFO = "";
	_variant_t varREALINFO = pRecordset->Fields->GetItem("REALINFO")->Value;
	if (varREALINFO.vt != VT_NULL) {
		strREALINFO = (const char*)_bstr_t(varREALINFO.bstrVal);
	}

	std::string strALARMINFO = "";
	_variant_t varALARMINFO = pRecordset->Fields->GetItem("ALARMINFO")->Value;
	if (varALARMINFO.vt != VT_NULL) {
		strALARMINFO = (const char*)_bstr_t(varALARMINFO.bstrVal);
	}

	// 创建 JSON 对象
	Json::Value jsonData;
	jsonData["ts"] = GetUnixTime();
	jsonData["values"]["ts"] = jsonData["ts"];
	jsonData["values"]["dataType"] = "LDF";
	jsonData["values"]["deviceType"] = "";
	jsonData["values"]["wellInfo"]["wellname"] = wellname;
	jsonData["values"]["wellInfo"]["wellId"] = "";
	jsonData["values"]["wellInfo"]["wellboreId"] = "";
	jsonData["values"]["data"]["WELLTIME"] = strTime;
	jsonData["values"]["data"]["TVOL01"] = dTvol01;
	jsonData["values"]["data"]["TVOL02"] = dTvol02;
	jsonData["values"]["data"]["TVOL03"] = dTvol03;
	jsonData["values"]["data"]["TVOL04"] = dTvol04;
	jsonData["values"]["data"]["TVOL05"] = dTvol05;
	jsonData["values"]["data"]["TVOL06"] = dTvol06;
	jsonData["values"]["data"]["TVOL07"] = dTvol07;
	jsonData["values"]["data"]["TVOL08"] = dTvol08;
	jsonData["values"]["data"]["TVOL09"] = dTvol09;
	jsonData["values"]["data"]["TVOL10"] = dTvol10;
	jsonData["values"]["data"]["TVOL11"] = dTvol11;
	jsonData["values"]["data"]["TVOL12"] = dTvol12;
	jsonData["values"]["data"]["TVOL13"] = dTvol13;
	jsonData["values"]["data"]["TVOL14"] = dTvol14;
	jsonData["values"]["data"]["TVOL15"] = dTvol15;
	jsonData["values"]["data"]["TVOL16"] = dTvol16;
	jsonData["values"]["data"]["TVOL17"] = dTvol17;
	jsonData["values"]["data"]["TVOL18"] = dTvol18;
	jsonData["values"]["data"]["TVOL19"] = dTvol19;
	jsonData["values"]["data"]["TVOL20"] = dTvol20;
	jsonData["values"]["data"]["TVOL21"] = dTvol21;
	jsonData["values"]["data"]["TVOL22"] = dTvol22;
	jsonData["values"]["data"]["TVOL23"] = dTvol23;
	jsonData["values"]["data"]["TVOL24"] = dTvol24;
	jsonData["values"]["data"]["SPM1"] = dSpm1;
	jsonData["values"]["data"]["SPM2"] = dSpm2;
	jsonData["values"]["data"]["SPM3"] = dSpm3;
	jsonData["values"]["data"]["CONIN"] = dConin;
	jsonData["values"]["data"]["CONOUT"] = dConout;
	jsonData["values"]["data"]["FLOWOUT"] = dFlowout;
	jsonData["values"]["data"]["CLOUT"] = dClout;
	jsonData["values"]["data"]["TVOL"] = dTvol;
	jsonData["values"]["data"]["MUDGL"] = dMudgl;
	jsonData["values"]["data"]["TTVOL"] = dTtvol;
	jsonData["values"]["data"]["TTVOLGL"] = dTtvolgl;
	jsonData["values"]["data"]["MUDGLRATE"] = dMudglrate;
	jsonData["values"]["data"]["TTVOLGLRATE"] = dTtvolglrate;
	jsonData["values"]["data"]["TOTALPUMP"] = dTotalpump;
	jsonData["values"]["data"]["FLOWIN"] = dFlowin;
	jsonData["values"]["data"]["FLOWDIFF"] = dFlowdiff;
	jsonData["values"]["data"]["CONDIFF"] = dCondiff;
	jsonData["values"]["data"]["TVOLBL"] = dTvolbl;
	jsonData["values"]["data"]["GS"] = dGs;
	jsonData["values"]["data"]["LS"] = dLs;
	jsonData["values"]["data"]["CS"] = dCs;
	jsonData["values"]["data"]["WSVOL"] = dWsv;
	jsonData["values"]["data"]["DEPTH"] = dDepth;
	jsonData["values"]["data"]["BITDEPTH"] = dBitdepth;
	jsonData["values"]["data"]["SPP"] = dSpp;
	jsonData["values"]["data"]["CASEP"] = dCasep;
	jsonData["values"]["data"]["TG"] = dTg;
	jsonData["values"]["data"]["REALINFO"] = strREALINFO;
	jsonData["values"]["data"]["ALARMINFO"] = strALARMINFO;
	// 添加 TVOL 信息
	for (int i = 0; i < 24; ++i) {
		jsonData["values"]["data"][std::string("TVOL") + std::to_string(i + 1) + "_INFO"] = strTVOLInfo[i];
	}
	// 返回生成的 JSON 字符串
	return toString(jsonData);
}


unsigned long long GetOldRecordCount(_ConnectionPtr& connection, const std::string& tableName, const std::string& oldtime)
{
	_RecordsetPtr pRecordset;
	pRecordset.CreateInstance(__uuidof(Recordset));
	CString sqlQuery;
	sqlQuery.Format(_T("SELECT COUNT(*) AS TotalCount FROM %s WHERE [TIME] > #%s#"), tableName.c_str(), oldtime.c_str());
	pRecordset->Open(
		sqlQuery.GetBuffer(),
		_variant_t((IDispatch*)connection, true),
		adOpenStatic,
		adLockOptimistic,
		adCmdText);
	std::string totalCountStr = _bstr_t(pRecordset->Fields->GetItem("TotalCount")->Value);
	unsigned long long totalRecords = std::stoull(totalCountStr);
	pRecordset->Close();
	return totalRecords;
}


UINT  Thread(LPVOID pParam)
{
	Tinco* inco = static_cast<Tinco*>(pParam);
	CDataSynApp* dlg = inco->appDlg;
	int nParam = inco->type;
	// TODO: 在此添加额外的初始化代码
	HRESULT hr = CoInitialize(NULL); // 初始化COM库
	if (FAILED(hr)) {
		AfxMessageBox(_T("Failed to initialize COM library"));
		return FALSE;
	}
	std::string tt;
	std::string sjk;
	std::string sql_time;

	// 定义连接和记录集对象
	_ConnectionPtr pConnection;
	_RecordsetPtr pRecordset;
	try {
		dlg->readini();
		// 创建连接对象
		HRESULT hr = pConnection.CreateInstance(__uuidof(Connection));
		if (FAILED(hr)) {
			AfxMessageBox(_T("Failed to create ADO connection instance"));
			return 0;
		}
		std::string  sss = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=";
		sss += dlg->DBPath.GetString();
		sss += ";";
		// 打开数据库连接
		pConnection->Open(
			sss.c_str(),
			"", "", adModeUnknown);
		std::ofstream outfile("a.txt");  // 创建输出文件流对象

		// 创建记录集对象
		pRecordset.CreateInstance(__uuidof(Recordset));
		while (dlg->b_work) {
			dlg->readini();
			if (nParam == 1)
			{
				tt = "LDF";
				sjk = "WITS_11";
				sql_time = dlg->BJtime.GetString();
			}
			else {
				tt = "DRL";
				sjk = "WITS_91";
				sql_time = dlg->ZGtime.GetString();

			}
			unsigned long long totalRecords = 0;
			unsigned long long sendto = 0;
			totalRecords = GetOldRecordCount(pConnection, sjk, sql_time);

			GetSet(pConnection);
			if (totalRecords == 0) {
				Sleep(10 * 1000);
				continue;
			}

			std::string tmp = "-历史";
			if (totalRecords ==1 ) {
				tmp = "-实时";
			}


			CString sqlQuery;
			sqlQuery.Format(_T("SELECT * FROM %s WHERE [TIME] > #%s#"), sjk.c_str(), sql_time.c_str());
			pRecordset->Open(
				sqlQuery.GetBuffer(),  // 查询SQL语句
				_variant_t((IDispatch*)pConnection, true),
				adOpenStatic,
				adLockOptimistic,
				adCmdText);


			unsigned long long num = 0;
			char buf[1024];
			while (!pRecordset->adoEof && dlg->b_work) {
				std::string ss;
				std::string strTime;

				if (nParam == 1)
				{
					//PostJsonToUrl("url", ss); 向api发送json
					ss = ConvertRecordsetToJson(pRecordset, dlg->strWellName.GetString());
					strTime = (const TCHAR*)_bstr_t(pRecordset->Fields->GetItem("TIME")->Value);
					dlg->m_listBox.InsertItem(num, tt.c_str());
					std::string t = strTime + tmp + tt;
					dlg->m_listBox.SetItemText(num, 1, t.c_str());

					//api send over
					sprintf_s(buf, sizeof(buf), "%llu", totalRecords - sendto);
					dlg->chi_non.SetWindowText(buf);
					sprintf_s(buf, sizeof(buf), "%llu", sendto);
					dlg->chi_send.SetWindowText(buf);
				}
				else {
					//PostJsonToUrl("url", ss); 向api发送json
					//ss = ConvertRecordsetToJson_zg(pRecordset);
					strTime = (const TCHAR*)_bstr_t(pRecordset->Fields->GetItem("TIME")->Value);
					dlg->m_listBox_zg.InsertItem(num, tt.c_str());
					std::string t = strTime + tmp + tt;
					dlg->m_listBox_zg.SetItemText(num, 1, t.c_str());

					sprintf_s(buf, sizeof(buf), "%llu", totalRecords - sendto);
					dlg->zg_non.SetWindowText(buf);
					sprintf_s(buf, sizeof(buf), "%llu", sendto);
					dlg->zg_send.SetWindowText(buf);
				}
				num++;
				sendto++;

			/*	if (num % 10 == 0) {*/
					std::time_t t = std::time(nullptr); // Get the current time
					std::tm localTime;
					localtime_s(&localTime, &t);
					std::cout << "num=" << num << ", time=" << std::put_time(&localTime, "%Y-%m-%d %H:%M:%S") << ", json:" << ss << std::endl;
					outfile << "num=" << num << ", time=" << std::put_time(&localTime, "%Y-%m-%d %H:%M:%S") << ", json:" << ss << std::endl;
					outfile.flush();
				//}

				pRecordset->MoveNext();  // 移动到下一条记录
				if (nParam == 1){
					iniData[_T("SendDateTime")][_T("BJtime")] = strTime.c_str();
					dlg->m_listBox.SendMessage(LVM_SCROLL, 0, 65535);
				}
				else {
					iniData[_T("SendDateTime")][_T("ZGtime")] = strTime.c_str();
					dlg->m_listBox_zg.SendMessage(LVM_SCROLL, 0, 65535);
				}

				WriteIniFile(dlg->exePath, iniData);
				Sleep(400);
			}

			pRecordset->Close();
		
		}
		outfile.close();  // 关闭文件

		// 关闭记录集和连接
		pConnection->Close();
	}
	catch (_com_error& e) {
		CString errorMsg;
		errorMsg.Format(_T("Error: %s\nDescription: %s\nCode: %08X"),
			e.ErrorMessage(),
			(LPCTSTR)e.Description(),
			e.Error());
		AfxMessageBox(errorMsg);
	}
	return 0;
}

void CDataSynApp::OnBnClickedButton1()
{
	if (b_work)
	{
		return;
	}
	b_work = true;

	CString s = "数据远传同步 V2024.09.20 " ;
	CString SendType = iniData[_T("SendData")][_T("SendType")];
	if (SendType == "0")
	{
		s += "内网传输";
		strSendRemote = "10.76.204.106";
	}
	else
	{
		strSendRemote = "114.251.197.140";
		s += "外网传输";
	}
	SetWindowText(s);

	CButton* pButton = (CButton*)GetDlgItem(IDC_BUTTON1);
	if (pButton != nullptr) {
		pButton->SetWindowText(_T("正在传输......"));
	}
	CString isok = iniData[_T("POSTGRESOLCFG")][_T("isok")];
	if (isok == "1")
	{
		
	}
	else
	{
		iniData[_T("Data")][_T("DRILLID")] = DRILLID;
		iniData[_T("AccessDB")][_T("DBPath")] = DBPath;
		WriteIniFile(exePath, iniData);
		Tinco ti;
		ti.appDlg = this;
		ti.type = 2;
		CWinThread* pThread = ::AfxBeginThread(Thread, &ti);
		if (pThread != NULL)
		{
			TRACE(_T("Thread started, ID: %u\n"), pThread->m_nThreadID);
		}
		else
		{
			::AfxMessageBox(_T("Failed to create thread."));
		}

		Tinco ti1;
		ti1.appDlg = this;
		ti1.type = 1;
		CWinThread* pThread1 = ::AfxBeginThread(Thread, &ti1);
		if (pThread != NULL)
		{
			TRACE(_T("Thread started, ID: %u\n"), pThread1->m_nThreadID);
		}
		else
		{
			::AfxMessageBox(_T("Failed to create thread."));
		}

	}


	UpdateData(TRUE);

	
}




void CDataSynApp::OnBnClickedButton3()
{
	// Create a CFileDialog object
	CFileDialog fileDlg(TRUE); // TRUE for file open dialog

	// Set the dialog title
	fileDlg.m_ofn.lpstrTitle = _T("请选择文件：");

	// Set default file extension (optional)
	fileDlg.m_ofn.lpstrDefExt = _T("txt");

	// Display the dialog
	if (fileDlg.DoModal() == IDOK)
	{
		// Get the selected file path
		CString __DBPath = fileDlg.GetPathName();
		if (__DBPath!= DBPath)
		{
			OnBnClickedButton2();
			m_listBox.DeleteAllItems();
			m_listBox_zg.DeleteAllItems();

			DBPath = __DBPath;
			iniData[_T("SendDateTime")][_T("BJtime")] = "";
			iniData[_T("SendDateTime")][_T("ZGtime")] = "";

			iniData[_T("AccessDB")][_T("DBPath")] = __DBPath;
			iniData[_T("Data")][_T("WELLID")] = "";
			iniData[_T("Data")][_T("DRILLID")]="";

			DRILLID = "";

			WriteIniFile(exePath, iniData);

			//fileName = DBPath;
			//int lastSlashPos = fileName.ReverseFind('\\');
			//if (lastSlashPos != -1)
			//	fileName = fileName.Mid(lastSlashPos + 1);

			//// 去除文件扩展名
			//int dotPos = fileName.ReverseFind(_T('.'));
			//if (dotPos != -1)
			//	fileName = fileName.Left(dotPos);
			//jing_name.SetWindowTextA(fileName);


			CButton* pButton = (CButton*)GetDlgItem(IDC_BUTTON3);
			if (pButton != nullptr) {
				pButton->SetWindowText(strWellName);
			}

			std::map<CString, std::map<CString, CString>> ini;
			ini.swap(iniData);
			readini();
		}
		// 提取文件名（不包括路径）
		strWellName = __DBPath;
		int lastSlashPos = strWellName.ReverseFind('\\');
		if (lastSlashPos != -1)
			strWellName = strWellName.Mid(lastSlashPos + 1);

		// 去除文件扩展名
		int dotPos = strWellName.ReverseFind(_T('.'));
		if (dotPos != -1)
			strWellName = strWellName.Left(dotPos);
		jing_name.SetWindowTextA(strWellName);
		// 输出文件名
		std::cout << "选择的文件名：" << strWellName.GetString() << std::endl;

		CButton* pButton = (CButton*)GetDlgItem(IDC_BUTTON3);
		if (pButton != nullptr) {
			pButton->SetWindowText(strWellName);
		}

	}
	else
	{
		std::cout << "No file selected." << std::endl;
	}
	UpdateData(false);
}


void CDataSynApp::OnBnClickedButton4()
{
	b_work = false;
	OnCancel();
}



// Utility to trim whitespace
CString Trim(const CString& str) {
	CString result(str);
	result.TrimLeft();
	result.TrimRight();
	return result;
}

// Function to read an INI file
std::map<CString, std::map<CString, CString>> ReadIniFile(const CString& filePath) {
	CStdioFile file;
	std::map<CString, std::map<CString, CString>> iniData;
	CString currentSection;

	if (file.Open(filePath, CFile::modeRead)) {
		CString line;
		while (file.ReadString(line)) {
			line = Trim(line);

			// Skip empty lines or comments
			if (line.IsEmpty() || line[0] == ';' || line[0] == '#') {
				continue;
			}

			// Detect section headers
			if (line[0] == '[' && line[line.GetLength() - 1] == ']') {
				currentSection = line.Mid(1, line.GetLength() - 2);
			}
			// Handle key-value pairs
			else if (!currentSection.IsEmpty()) {
				int equalsPos = line.Find('=');
				if (equalsPos != -1) {
					CString key = Trim(line.Left(equalsPos));
					CString value = Trim(line.Mid(equalsPos + 1));
					iniData[currentSection][key] = value;
				}
			}
		}
		file.Close();
	}
	return iniData;
}

// Function to write back to an INI file
void WriteIniFile(const CString& filePath, const std::map<CString, std::map<CString, CString>>& iniData) {
	m_mutex.Lock(); // 获取互斥锁
	CStdioFile file;
	if (file.Open(filePath, CFile::modeWrite | CFile::modeCreate)) {
		for (const auto& section : iniData) {
			file.WriteString(_T("[") + section.first + _T("]\n"));
			for (const auto& keyValue : section.second) {
				file.WriteString(keyValue.first + _T("=") + keyValue.second + _T("\n"));
			}
			file.WriteString(_T("\n"));
		}
		file.Close();
	}
	m_mutex.Unlock(); // 释放互斥锁
}


void CDataSynApp::OnBnClickedButton2()
{
	b_work = false;
	CButton* pButton = (CButton*)GetDlgItem(IDC_BUTTON1);

	// Ensure the button exists
	if (pButton != nullptr) {
		// Change the button's text to "New Button Text"
		pButton->SetWindowText(_T("开始传输"));
	}
}


void CDataSynApp::OnClose()
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	CDialogEx::OnClose();
}


void CDataSynApp::OnCancel()
{
	// 显示确认对话框
	int result = AfxMessageBox(_T("确定要关闭窗口吗？"), MB_YESNO | MB_ICONQUESTION);

	if (result == IDYES)
	{
		// 用户选择“是”，关闭窗口
		curl_global_cleanup();

		CDialogEx::OnCancel();
	}
	else
	{
		// 用户选择“否”，不关闭窗口
		return;
	}
}


void CDataSynApp::OnStnClickedStaticpic()
{
	Set dlg;

	// 显示模态对话框，主窗口会在对话框关闭之前被阻塞
	dlg.DoModal();
}


void CDataSynApp::OnBnClickedButton5()
{
	// TODO: 在此添加控件通知处理程序代码
}
